package com.yisu.expressway.ui.recyclerview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;


import com.yisu.expressway.R;
import com.yisu.expressway.utils.StringUtil;
import com.yisu.expressway.utils.ToastUtil;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by will on 16/2/22.
 */
public class PagingRecyclerView extends RecyclerView {

    public boolean ignoreTouchEvent = false;

    public int pageSize = 20;
    private int total = -1;
    private int start = 0;
    private boolean isLoading;

    private SwipeRefreshLayout refreshLayout;

    private DataAdapter dataAdapter;
    private View loadmoreView;
    private View loadNoMoreView;
    private LayoutManager layoutManager;
    private OnPageRefreshListener pageRefreshListener;

    public boolean isShowNotNoMore=true;
    public PagingRecyclerView(Context context) {
        super(context);
        initView();
    }

    public PagingRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public PagingRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    public void init(SampleActionListener listener){
        init(null, layoutManager, listener);
    }
    public void init(SampleActionListener listener, int limit){
        pageSize = limit;
        init(null, layoutManager, listener);
    }
    public void init(ItemDecoration itemDecoration,
                     LayoutManager layoutManager, SampleActionListener listener) {
        init(itemDecoration, layoutManager, listener, pageSize);
    }

    public boolean isRefresh() {
        return isRefresh;
    }

    public void setRefresh(boolean refresh) {
        isRefresh = refresh;
    }

    public  boolean isRefresh;

    public interface OnPageRefreshListener {
          boolean getRefreshStatus();
    }

    public void setOnPageRefreshListener(OnPageRefreshListener l){
        pageRefreshListener=l;
    }

    public boolean getRefreshStatus(){

      return isRefresh();
    }

    public void initView(){
        layoutManager = new LinearLayoutManagerWrapper(getContext());
        setLayoutManager(layoutManager);
        setAdapter(dataAdapter = new DataAdapter(getContext()));
//        loadmoreView = LayoutInflater.from(getContext())
//                .inflate(R.layout.load_more_footer, this, false);
//        loadNoMoreView=LayoutInflater.from(getContext()).inflate(R.layout.load_no_more_footer,this,false);
    }

    public void setHeaderView(View headerView){
        dataAdapter.setHeaderView(headerView);
    }

    public void init(ItemDecoration itemDecoration,
                     LayoutManager _layoutManager, SampleActionListener listener, int limit, boolean canSwipeRefresh){
        this.layoutManager = _layoutManager;
        pageSize = limit;
        sampleActionListener = listener;
        if (itemDecoration != null)
            addItemDecoration(itemDecoration);
        setLayoutManager(layoutManager);
//        setAdapter(dataAdapter = new DataAdapter(getContext()));
        dataAdapter.setData(new ArrayList<>());
//        loadmoreView = LayoutInflater.from(getContext())
//                .inflate(R.layout.load_more_footer, this, false);
//
        if (getParent() instanceof SwipeRefreshLayout){
            refreshLayout = (SwipeRefreshLayout)getParent();
            if(!canSwipeRefresh){
                refreshLayout.setEnabled(false);
            }else {

                refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
                    @Override
                    public void onRefresh() {
//                        HBLog.e("yxq", "已经刷新了");
                        if(pageRefreshListener!=null){
                            pageRefreshListener.getRefreshStatus();
                        }
                        setRefresh(true);
                        refreshData();
                    }
                });

            }
        }

        refreshData();

        /**判断是否滑动到底部**/
        addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    int lastVisibleItemPosition = 0;
                    int totalItemCount = layoutManager.getItemCount();
                    int visibleItemCount = layoutManager.getChildCount();

                    if(layoutManager != null ){
                        if(layoutManager instanceof ExStaggeredGridLayoutManager) {
                            ExStaggeredGridLayoutManager manager = (ExStaggeredGridLayoutManager) layoutManager;
                            int[] lastVisibleItem = manager.findLastCompletelyVisibleItemPositions(null);
                            int spanCount = manager.getSpanCount();
                            lastVisibleItemPosition = lastVisibleItem[spanCount - 1];
                        }else if(layoutManager instanceof LinearLayoutManager){
                            lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
                        }else if(layoutManager instanceof GridLayoutManager){
                            lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
                        }

                        if (visibleItemCount > 0 && lastVisibleItemPosition >= (totalItemCount - 1)){
                            loadMore();
                        }
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
//                if (!recyclerView.canScrollVertically(-1)) {
////                    onScrolledToTop();
//                } else if (!recyclerView.canScrollVertically(1)) {
////                    onScrolledToBottom();
//                    loadMore();
//                } else if (dy < 0) {
////                    onScrolledUp();
//                } else if (dy > 0) {
////                    onScrolledDown();
//                }
            }
        });
    }

    private int findMax(int[] lastPositions) {
        int max = lastPositions[0];
        for (int value : lastPositions) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    public void setData(ArrayList datas){
        if (dataAdapter != null)
            dataAdapter.setData(datas);
        isLoading = false;
    }
    public void setSampleActionListener(SampleActionListener listener){
        sampleActionListener = listener;
    }


    public void init(ItemDecoration itemDecoration,
                     LayoutManager layoutManager, SampleActionListener listener, int limit){
        init(itemDecoration, layoutManager, listener, limit, true);
    }

    public void refreshData(){
        dataAdapter.removeFooter();
        initLoadParams();
        fetchData(true);
    }

    private void loadMore(){
        if (dataAdapter.getData().size() < total) {// load more
            start = dataAdapter.getData().size();
            fetchData(false);
        }
    }

    private void initLoadParams(){
        start = 0;
        total = -1;
    }
//    boolean hasFooter;
    private void fetchData(boolean showRefresh) {
//        hasFooter = false;
        if (sampleActionListener != null && !isLoading) {
//            hasFooter = dataAdapter.hasFooter();
//            dataAdapter.removeFooter();
            if (showRefresh && refreshLayout != null && !refreshLayout.isRefreshing())
                refreshLayout.setRefreshing(true);
            isLoading = true;
            sampleActionListener.fetchData(start, pageSize);
        }
    }


    public boolean dataFetchDone(List _datas){
        return dataFetchDone(_datas, -1);
    }

    public boolean dataFetchDone(List _datas, int totalCount){




        if (//_datas != null && _datas.size() > 0 &&
                start == 0){
            dataAdapter.getData().clear();
        }

        ArrayList mOldDataList = dataAdapter.getData();

        boolean last = false;
        if (totalCount > 0){
            total = totalCount;
        }else if (_datas == null || _datas.size() == 0 || _datas.size() < pageSize){
            total = dataAdapter.getData().size();
            if (_datas != null && _datas.size() > 0 && _datas.size() < pageSize){
                total += _datas.size();
            }
        }else if (totalCount < 0){
            total = Integer.MAX_VALUE;
        }

        if (_datas != null && _datas.size() > 0){
            dataAdapter.getData().addAll(_datas);
        }

        if (dataAdapter.getData().size() < total) {
            if(_datas == null || _datas.size() == 0 || _datas.size() < pageSize){
                loadNoMoreView = LayoutInflater.from(getContext())
                        .inflate(R.layout.load_no_more_footer, this, false);
                if(isShowNotNoMore){
                    dataAdapter.setFooterViewNoNotify(loadNoMoreView);
                }
            }else{
                loadmoreView = LayoutInflater.from(getContext())
                        .inflate(R.layout.load_more_footer, this, false);
                dataAdapter.setFooterViewNoNotify(loadmoreView);
            }
        }else{
            dataAdapter.removeFooterNoNotify();
            last = true;
            if (sampleActionListener != null && sampleActionListener instanceof  DataFetchStatusListener) {
                DataFetchStatusListener dataFetchStatusListener = (DataFetchStatusListener)sampleActionListener;
                if (start == 0) {
                    if (dataAdapter.getData().size() == 0) {
                        dataFetchStatusListener.allDataFetchDoneStart();
                    } else {
                        dataFetchStatusListener.allDataFetchStart();
                    }
                } else {
                    if (_datas == null || _datas.size() == 0) {
                        dataFetchStatusListener.allDataFetchDoneEnd();
                    }
                }
            }
        }
        if (refreshLayout != null)
            refreshLayout.setRefreshing(false);
        isLoading = false;


//        if(_datas != null && _datas.size() > 0 && start != 0) {
//            int startOffset = mOldDataList == null ? 0 : mOldDataList.size();//dataAdapter.hasHeader() ? TotaldataSize + 1 : TotaldataSize;
//            dataAdapter.notifyItemRangeInserted(startOffset, _datas.size());
//        }else{
//            dataAdapter.notifyDataSetChanged();
//        }

        if(_datas == null || _datas.size() == 0 ){
            dataAdapter.notifyDataSetChanged();
        } else {
            if (start > 0) {
                int startOffset = mOldDataList == null ? 0 : mOldDataList.size();//dataAdapter.hasHeader() ? TotaldataSize + 1 : TotaldataSize;
                dataAdapter.notifyMyItemRangeInserted(startOffset, _datas.size());
            }else
                dataAdapter.notifyDataSetChanged();
        }

        return last;
    }

    public void dataFetchFail(String msg){
        if (refreshLayout != null)
            refreshLayout.setRefreshing(false);
//        if (hasFooter){
//            dataAdapter.setFooterView(loadmoreView);
//        }
        isLoading = false;
        if (getContext() != null&& !StringUtil.isNullOrEmpty(msg))
            ToastUtil.displayShortToastMsg(getContext(),msg);
    }

    public void dataFetchFail(int stringId){
        if (refreshLayout != null)
            refreshLayout.setRefreshing(false);
//        if (hasFooter){
//            dataAdapter.setFooterView(loadmoreView);
//        }
        isLoading = false;
        if (getContext() != null)
            ToastUtil.displayShortToastMsg(getContext(), stringId);
    }

    public void remove(int position) {
        Object remove = dataAdapter.getData().remove(position);
        if (remove != null) {
            dataAdapter.notifyMyItemRemoved(position);
            dataAdapter.notifyMyItemRangeChanged(position, dataAdapter.getDataItemCount() - position + 1);
        }
    }

    public DataAdapter getDataAdapter(){
        return dataAdapter;
    }

    private SampleActionListener sampleActionListener;

//    private DataFetchStatusListener dataFetchStatusListener;


    public interface SampleActionListener {
        void fetchData(int start, int pageSize);

        BaseRvAdapter.SampleViewHolder createItemViewHolder(ViewGroup parent, int viewType);
        void bindData(BaseRvAdapter.SampleViewHolder holder, int position, Object item);
    }
    public interface CustomItemTypeActionListener extends SampleActionListener {
        int getDataItemType(int position);
    }
    public interface DataFetchStatusListener extends SampleActionListener {
        void allDataFetchDoneStart();
        void allDataFetchStart();
        void allDataFetchDoneEnd();
    }

    public interface ViewHoderStatusListener extends CustomItemTypeActionListener {
        void viewRecycled(BaseRvAdapter.SampleViewHolder viewHolder);
    }

    public interface ViewHolderBindHeaderListener extends SampleActionListener{
        void onBindHeaderView(BaseRvAdapter.SampleViewHolder headerViewHolder);
    }

    public class DataAdapter extends HFRecyclerViewAdapter<Object, BaseRvAdapter.SampleViewHolder>{

        public DataAdapter(Context context) {
            super(context);
        }

        /**弃用判断footer是否可见来决定是否到尾部**/
        @Override
        public void footerOnVisibleItem() {
//            if(layoutManager != null && !(layoutManager instanceof ExStaggeredGridLayoutManager)
//                     ) {
//                loadMore();
//            }
        }

        @Override
        public BaseRvAdapter.SampleViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) {
            return sampleActionListener != null ? sampleActionListener.createItemViewHolder(parent, viewType) : null;
        }

        @Override
        public void onBindHeaderView(SampleViewHolder headerViewHolder) {
            if (sampleActionListener != null && sampleActionListener instanceof ViewHolderBindHeaderListener){
                ((ViewHolderBindHeaderListener) sampleActionListener).onBindHeaderView(headerViewHolder);
            }
        }

        @Override
        public void onBindDataItemViewHolder(BaseRvAdapter.SampleViewHolder holder, int position) {
            if (sampleActionListener != null)
                sampleActionListener.bindData(holder, position, getData().get(position));
        }

        @Override
        public int getDataItemType(int position) {
            if (sampleActionListener != null && sampleActionListener instanceof CustomItemTypeActionListener){
                return ((CustomItemTypeActionListener) sampleActionListener).getDataItemType(position);
            }
            return super.getDataItemType(position);
        }

        @Override
        public void onViewRecycled(SampleViewHolder holder) {

            if (sampleActionListener != null && sampleActionListener instanceof ViewHoderStatusListener){
                ((ViewHoderStatusListener) sampleActionListener).viewRecycled(holder);
            }
            super.onViewRecycled(holder);
        }
    }

//    @Override
//    public LayoutManager getLayoutManager() {
//        return layoutManager;
//    }

    public SwipeRefreshLayout getSwipeRefreshLayout(){
        return refreshLayout;
    }

    @Override
    public void setLayoutManager(LayoutManager layoutManager){
        super.setLayoutManager(layoutManager);
        this.layoutManager = layoutManager;
    }



    public void smoothMoveToPosition(int n) {

        if (layoutManager instanceof LinearLayoutManager) {
            LinearLayoutManager lManager = (LinearLayoutManager)layoutManager;
            int firstItem = lManager.findFirstVisibleItemPosition();
            int lastItem = lManager.findLastVisibleItemPosition();
//            if (n <= firstItem) {
//                smoothScrollToPosition(n);
//            } else if (n <= lastItem) {
//                int top = getChildAt(n - firstItem).getTop();
//                smoothScrollBy(0, top);
//            } else {
//                smoothScrollToPosition(n);
//            }

            if (n <= firstItem) {
                smoothScrollToPosition(n);
            } else if (n <= lastItem) {
                int top = getChildAt(n - firstItem).getTop();
                smoothScrollBy(0, top);
            } else {
                smoothScrollToPosition(n);
            }


//            smoothScrollToPosition(n);
        }

    }


    //
    private int mFadingEdgeHeight;
    private Paint mGradientPaint;

    private final int mOpaque = 0xFF000000;
    private final int mTransparent = Color.TRANSPARENT;

    private boolean fadingEdge;
    public void setFadingEdge(boolean enable){
        fadingEdge = enable;
        mFadingEdgeHeight = 70;
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        if (mGradientPaint == null){
            Shader shader = new LinearGradient(0, Math.round(mFadingEdgeHeight * 0.2f), 0, mFadingEdgeHeight, mTransparent, mOpaque, Shader.TileMode.CLAMP);
            mGradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mGradientPaint.setShader(shader);
            mGradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        if (fadingEdge)
            canvas.drawRect(0, 0, getWidth(), mFadingEdgeHeight, mGradientPaint);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return !ignoreTouchEvent && super.dispatchTouchEvent(ev);
    }
}
